home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-02-07 | 8.6 KB | 288 lines | [TEXT/MPS ] |
- (*
- CTBRecvUpTo([termChar[,timeOut[,limit[,dontStrip]]]]) -- Receive characters until the termChar is
- received, or until timeOut 60ths of a second have passed. If the limit parameter is present, then
- only receive that many characters maximum. If the dontStrip parameter is present, then don't
- do control character or top bit stripping. If CTBRecvUpTo is called with no parameters, and it
- was previously called and returned due to reaching the character limit, then it will continue the
- previous receive with the same termChar, timeOut, limit, and dontStrip settings.
-
- To compile and link this file using Macintosh Programmer's Workshop,
-
- pascal -w CTBRecvUpTo.p
- link -m ENTRYPOINT -o HyperCommands -rt XFCN=2760 -sn Main=CTBRecvUpTo ∂
- CTBRecvUpTo.p.o "{MPW}"Libraries:interface.o "{MPW}"Libraries:Libraries:HyperXLib.o
-
- © Copyright 1990 by Apple Computer, Inc.
-
- Initial coding 2/90 by Harry R. Chesley.
- *)
-
- {$R-}
-
- {$S CTBRecvUpTo } { Segment name must be the same as the command name. }
-
- unit DummyUnit;
-
- interface
-
- uses MemTypes, QuickDraw, OSIntf, ToolIntf, CTBUtils, FTIntf, CMIntf, TMIntf, CRMIntf, HyperXCmd;
-
- procedure EntryPoint(paramPtr: XCmdPtr);
-
- implementation
-
- procedure CTBRecvUpTo(paramPtr: XCmdPtr); forward;
-
- procedure EntryPoint(paramPtr: XCmdPtr);
-
- begin
- CTBRecvUpTo(paramPtr);
- end;
-
- procedure CTBRecvUpTo(paramPtr: XCmdPtr);
-
- {$I CTBUtil.inc}
-
- var lookForTerm: boolean;
- termString: Ptr;
- termPtr, oldTermPtr: Ptr;
- stopAt: longInt;
- doStrip: boolean;
- gotIt: boolean;
- toRead: longInt;
- toCopy: longInt;
- oldSize: longInt;
- l, l2, l3: longInt;
- h: Handle;
- p: Ptr;
- sizes: CMBufferSizes;
- status: CMStatFlags;
- theBuf: InputBufferHandle;
- recvMax: longInt;
-
- procedure Fail(errMsg: Str255); { set theResult and quit }
- begin
- if lookForTerm then HUnlock(paramPtr^.params[1]);
- paramPtr^.returnValue := PasToZero(paramPtr,errMsg);
- exit(CTBRecvUpTo);
- end;
-
- begin
- { Check the number of parameters. }
- if paramPtr^.paramCount > 4 then Fail('Invalid parameter count');
-
- { Check that the Comm Toolbox is ready. }
- CTBReady;
- { And that we've got a connection tool. }
- EnsurePresent(connectionTool);
- { And it's open. }
- EnsureOpen;
- theBuf := InputBufferHandle(CMGetUserData(Globals^^.connHand));
-
- { Are we getting the next part due to a limit return? }
- if paramPtr^.paramCount = 0 then
- begin
- if theBuf^^.timeOut = -1 then exit(CTBRecvUpTo);
- { If so, then load the parameters from the saved globals. }
- if theBuf^^.termString <> nil then
- begin
- lookForTerm := true;
- HLock(theBuf^^.termString);
- termString := theBuf^^.termString^;
- termPtr := Ptr(ord4(termString)+theBuf^^.termOffset);
- end
- else lookForTerm := false;
- end
- else
- begin
- { If there's parameters already loaded, clear it out. }
- if theBuf^^.termString <> nil then
- begin
- DisposHandle(theBuf^^.termString);
- theBuf^^.termString := nil;
- end;
- { Get the termination string. }
- if ParmPresent(1) then
- begin
- theBuf^^.termString := paramPtr^.params[1];
- if HandToHand(theBuf^^.termString) <> noErr then
- begin
- theBuf^^.termString := nil;
- Fail('Could not allocate string space');
- end;
- lookForTerm := true;
- HLock(theBuf^^.termString);
- termString := theBuf^^.termString^;
- termPtr := termString;
- end
- else lookForTerm := false;
- { Get the time-out. }
- if ParmPresent(2) then theBuf^^.timeOut := GetLongParm(2)
- else theBuf^^.timeOut := 0;
- { Get the character limit. }
- if ParmPresent(3) then theBuf^^.recvLimit := GetLongParm(3)
- else theBuf^^.recvLimit := 50000;
- { Find out if we should strip. }
- if ParmPresent(4) then theBuf^^.doStrip := false
- else theBuf^^.doStrip := true;
- end;
-
- { Get all the parameters into easy-to-access form. }
- recvMax := theBuf^^.recvLimit;
- stopAt := TickCount + theBuf^^.timeOut;
- doStrip := theBuf^^.doStrip;
-
- { Allocate a results handle. }
- h := NewHandle(0);
- if h = nil then Fail('Out of memory');
-
- { Loop 'til we drop. }
- gotIt := false;
- repeat
- { If there's nothing left in the buffer, read more in. }
- if theBuf^^.amountLeft = 0 then
- begin
- { But only if there's something to read. }
- if CMStatus(Globals^^.connHand,sizes,status) = noErr then
- begin
- if BAnd(status,cmStatusOpening+cmStatusListenPend+cmStatusIncomingCallPresent+
- cmStatusOpen) = 0 then leave;
- toRead := min(sizes[cmDataIn],BUFFERSIZE)
- end
- else toRead := 0;
- if toRead > 0 then toRead := ReadFromConn(@theBuf^^.buffer,toRead);
- theBuf^^.bufferPtr := @theBuf^^.buffer;
- theBuf^^.amountLeft := toRead;
- end;
-
- { If there's anything to process, process it. }
- if theBuf^^.amountLeft > 0 then
- begin
- { Check for the termination string. }
- if lookForTerm then
- begin
- p := theBuf^^.bufferPtr;
- l := min(recvMax,theBuf^^.amountLeft);
- { Decide whether to loop and strip or just loop and look. Note: We have to strip now
- rather than after we've read everything because the termination string matches
- the data after it's been striped. }
- if doStrip then
- while l > 0 do
- begin
- l := l-1;
- if BAnd(p^,$7F) = termPtr^ then
- begin
- termPtr := Ptr(ord4(termPtr)+1);
- if termPtr^ = 0 then
- begin
- gotIt := true;
- leave;
- end;
- end
- else
- begin
- { If not, then recalculate where we are in the termination string. }
- l2 := ord4(termPtr)-ord4(termString)-1;
- oldTermPtr := termPtr;
- termPtr := termString;
- while l2 > 0 do
- begin
- p := Ptr(ord4(oldTermPtr)-l2);
- l3 := l2;
- while l3 > 0 do
- begin
- if p^ <> termPtr^ then leave;
- p := Ptr(ord4(p)+1);
- termPtr := Ptr(ord4(termPtr)+1);
- l3 := l3-1;
- end;
- if (l3 = 0) and (BAnd(p^,$7F) = termPtr^) then leave;
- l2 := l2-1;
- termPtr := termString;
- end;
- if BAnd(p^,$7F) = termPtr^ then termPtr := Ptr(ord4(termPtr)+1)
- else termPtr := termString;
- end;
- p := Ptr(ord4(p)+1);
- end
- else
- while l > 0 do
- begin
- l := l-1;
- if p^ = termPtr^ then
- begin
- termPtr := Ptr(ord4(termPtr)+1);
- if termPtr^ = 0 then
- begin
- gotIt := true;
- leave;
- end;
- end
- else
- begin
- { If not, then recalculate where we are in the termination string. }
- l2 := ord4(termPtr)-ord4(termString)-1;
- oldTermPtr := termPtr;
- termPtr := termString;
- while l2 > 0 do
- begin
- p := Ptr(ord4(oldTermPtr)-l2);
- l3 := l2;
- while l3 > 0 do
- begin
- if p^ <> termPtr^ then leave;
- p := Ptr(ord4(p)+1);
- termPtr := Ptr(ord4(termPtr)+1);
- l3 := l3-1;
- end;
- if (l3 = 0) and (p^ = termPtr^) then leave;
- l2 := l2-1;
- termPtr := termString;
- end;
- if p^ = termPtr^ then termPtr := Ptr(ord4(termPtr)+1)
- else termPtr := termString;
- end;
- p := Ptr(ord4(p)+1);
- end;
- end
- else l := 0;
- { Copy over whatever fits. }
- oldSize := GetHandleSize(h);
- toCopy := min(recvMax,theBuf^^.amountLeft) - l;
- SetHandleSize(h,oldSize + toCopy);
- if MemError <> noErr then
- begin
- DisposHandle(h);
- Fail('Out of memory');
- end;
- BlockMove(theBuf^^.bufferPtr,Ptr(ord4(h^) + oldSize),toCopy);
- theBuf^^.bufferPtr := Ptr(ord4(theBuf^^.bufferPtr) + toCopy);
- theBuf^^.amountLeft := theBuf^^.amountLeft - toCopy;
- recvMax := recvMax - toCopy;
- stopAt := TickCount + theBuf^^.timeOut;
- end
- else if (TickCount - stopAt) > 0 then leave;
-
- until gotIt or (recvMax = 0);
-
- { Unlock the termination string buffer. }
- if lookForTerm then HUnlock(theBuf^^.termString);
-
- { If we saw the termination, get rid of the termination/time-out information. }
- if gotIt then
- begin
- theBuf^^.timeOut := -1;
- DisposHandle(theBuf^^.termString);
- theBuf^^.termString := nil;
- end
- { Otherwise, remember it. }
- else theBuf^^.termOffset := ord4(termPtr)-ord4(termString);
-
- { Strip the results and return it. }
- StripBytes(h,GetHandleSize(h),doStrip);
-
- paramPtr^.returnValue := h;
- end;
-
- end.
-